/*
 *  Copyright 2011 Alexey Andreev.
 * 
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 * 
 *       http://www.apache.org/licenses/LICENSE-2.0
 * 
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *  under the License.
 */
package org.xthl.core;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import org.nop.core.AbstractController;
import org.nop.core.Content;
import org.nop.core.RouteBinding;
import org.nop.util.Injected;
import org.xthl.core.api.Block;
import org.xthl.core.api.BlockLogic;
import org.xthl.core.api.CustomBlock;
import org.xthl.core.api.SpecialBlock;
import org.xthl.core.api.UpdateCustomBlockCommand;
import org.xthl.core.view.AcceptRemoveBlockView;
import org.xthl.core.view.BlockEditForm;
import org.xthl.core.view.BlockEditView;
import org.xthl.core.view.BlockListForm;
import org.xthl.core.view.BlockListView;
import org.xthl.core.view.BlockType;
import org.xthl.core.view.EditableBlockSight;

/**
 *
 * @author Alexey Andreev
 */
@RouteBinding(BlocksRoute.class)
public class BlocksController extends AbstractController {
    private BlockLogic logic;
    
    @Injected
    public BlocksController(BlockLogic logic) {
        this.logic = logic;
    }

    public Content list(BlockListForm form) {
        List<Block> blocks = logic.getBlocks();
        List<EditableBlockSight> sightList = new ArrayList<EditableBlockSight>();
        for (Block block : blocks) {
            EditableBlockSight sight = new EditableBlockSight();
            sightList.add(sight);
            sight.setId(block.getId());
            sight.setMoveUpAvailable(true);
            sight.setMoveDownAvailable(true);
            sight.setEnabled(block.isEnabled());
            if (block instanceof CustomBlock) {
                CustomBlock custom = (CustomBlock)block;
                sight.setType(BlockType.CUSTOM);
                sight.setRemovable(true);
                sight.setTitle(custom.getTitle());
                sight.setContent("");
            } else if (block instanceof SpecialBlock) {
                SpecialBlock special = (SpecialBlock)block;
                sight.setType(BlockType.SPECIAL);
                sight.setTitle(special.getRendererType().getName());
                sight.setContent("");
                sight.setRemovable(false);
            }
        }
        if (!sightList.isEmpty()) {
            sightList.get(0).setMoveUpAvailable(false);
            sightList.get(sightList.size() - 1).setMoveDownAvailable(false);
        }
        return html(createView(BlockListView.class)
                .setForm(form)
                .setBlocks(sightList));
    }
    
    public Content enable(BlockListForm form) {
        if (!form.getSelectedBlockIds().isEmpty()) {
            logic.enableBlocks(form.getSelectedBlockIds(), true);
        }
        return list(form);
    }
    
    public Content disable(BlockListForm form) {
        if (!form.getSelectedBlockIds().isEmpty()) {
            logic.enableBlocks(form.getSelectedBlockIds(), false);
        }
        return list(form);
    }
    
    public Content moveUp(BlockListForm form) {
        if (form.getAffectedBlockIds().size() != 1) {
            return null;
        }
        int blockId = form.getAffectedBlockIds().iterator().next();
        Block block = logic.getBlock(blockId);
        if (block == null || block.getPosition() == 0) {
            return null;
        }
        logic.moveBlock(blockId, block.getPosition() - 1);
        return list(form);
    }
    
    public Content moveDown(BlockListForm form) {
        if (form.getAffectedBlockIds().size() != 1) {
            return null;
        }
        int blockId = form.getAffectedBlockIds().iterator().next();
        Block block = logic.getBlock(blockId);
        if (block == null) {
            return null;
        }
        logic.moveBlock(blockId, block.getPosition() + 1);
        return list(form);
    }
    
    public Content remove(BlockListForm form) {
        Integer blockId = form.getAffectedBlockId();
        if (blockId == null) {
            return null;
        }
        CustomBlock block = (CustomBlock)logic.getBlock(blockId);
        form.getSelectedBlockIds().remove(blockId);
        return html(createView(AcceptRemoveBlockView.class)
                .setForm(form)
                .setBlock(block));
    }
    
    public Content acceptRemove(BlockListForm form) {
        Integer blockId = form.getAffectedBlockId();
        if (blockId == null) {
            return null;
        }
        logic.deleteCustomBlock(blockId);
        return list(form);
    }
    
    public Content edit(BlockEditForm form, int blockId) {
        Block baseBlock = logic.getBlock(blockId);
        if (baseBlock == null || !(baseBlock instanceof CustomBlock)) {
            return null;
        }
        CustomBlock block = (CustomBlock)baseBlock;
        if (!form.isPosted()) {
            form.setTitle(block.getTitle());
            form.setContent(logic.getCustomBlockContent(blockId));
            form.setEnabled(block.isEnabled());
        }
        return html(createView(BlockEditView.class)
                .setBlock(block)
                .setForm(form));
    }
    
    public Content save(BlockEditForm form, int blockId) {
        UpdateCustomBlockCommand command = new UpdateCustomBlockCommand();
        command.setTitle(form.getTitle());
        command.setContent(form.getContent() != null ? form.getContent() : "");
        logic.updateCustomBlock(blockId, command);
        logic.enableBlocks(new HashSet<Integer>(Arrays.asList(blockId)), form.isEnabled());
        return edit(form, blockId);
    }
    
    public Content remove(@SuppressWarnings("unused") BlockEditForm form, int blockId) {
        BlockListForm listForm = new BlockListForm();
        listForm.getAffectedBlockIds().add(blockId);
        return remove(listForm);
    }
    
    public Content add(BlockEditForm form) {
        return html(createView(BlockEditView.class)
                .setBlock(null)
                .setForm(form));
    }
    
    public Content save(BlockEditForm form) {
        String content = form.getContent() != null ? form.getContent() : "";
        int blockId = logic.createCustomBlock(form.getTitle(), content);
        logic.enableBlocks(new HashSet<Integer>(Arrays.asList(blockId)), form.isEnabled());
        return redirect(route(BlocksRoute.class).edit(blockId));
    }
}
